var ui;         // access XUL elements through this
var wpl;        // WebProgressListener
var sbox;       // hover selection box

function onLoad() {   
    ui = getUiObject(document);
    wpl = new WebProgressListener(ui.progress, ui.urlbar, ui.status);
    wpl.onDocumentStop = setupHoverSelection;
    ui.browser.addProgressListener(wpl, 
                Components.interfaces.nsIWebProgress.NOTIFY_ALL);
    
    setupEventHandling();
    
    ui.urlbar.focus();
}

function setupEventHandling() {
    setupKeyHandling();

    // Automatically unselect the box when the mouse leaves the browser pane:
    $(ui.browserPane).bind("mouseout", function() {
        if (sbox)
            sbox.deselect();
    });
    // Bring focus back to browser when mouse enters browser pane:
    $(ui.browserPane).bind("mouseover", function() {
        ui.browser.focus();
    });
    
    $("#queryToggle").bind("command", function() {
        if (ui.queryToggle.label == "CSS") 
            ui.queryToggle.label = "XPath";
        else
            ui.queryToggle.label = "CSS";
    });
}

function setupKeyHandling() {
    $(window).keypress(function(e) {
        processKeyCommands(e.which);
    });

    // Press ENTER to load the URL
    $("#urlbar").keypress(function(e) {
        if (e.which == 13) loadUrl();
    });
    
    // Press F5 to execute the query:
    $("#execKey").attr({oncommand: "execQuery()"});
    // Press Ctrl+l to bring focus to URL bar:
    $("#urlbarKey").attr({oncommand: "focusTextBox(ui.urlbar);"});
    // Press Ctrl+k to bring focus to query box:
    $("#queryKey").attr({oncommand: "focusTextBox(ui.query);"});
    // Press ESC to clear the query select boxes:
    $("#clearQueryKey").attr({oncommand: "clearQuery();"});
}

function processKeyCommands(/*int*/ charCode) {
    var keyChar = String.fromCharCode(charCode);

    switch(keyChar) {
        case "w": 
            updateMeta(sbox.widen());
            break;
        case "n": 
            updateMeta(sbox.narrow());
            break;
    }
}

function loadUrl() {
    var url = ui.urlbar.value;    
    ui.browser.loadURI(url, null, null);
        
    // Apparently, binding to window.onload does not work when loading 
    // subsequent documents:
    // $(ui.browser.contentDocument).ready(setupHoverSelection);
}

function setupHoverSelection() {
    sbox = null;
    var elements = $('*', ui.browser.contentDocument.body);
    sbox = createHoverSelectBox(ui.browser.contentDocument);

    var hoverFn = function(e) {
        sbox.select(this);
        updateMeta(this);
        e.stopPropagation();
    };
    
    elements.bind("mouseover", hoverFn);
}

function updateMeta(/*HTMLElement*/ node) {
    var text = node.nodeName.toLowerCase();
    var childCount = node.childNodes.length;
    
    if (node.id)
        text += ", id: " + node.id;
    if (node.className)
        text += ", class: " + node.className;
        
    var nodeNames = [];
    while (true) {
        if (node.nodeName == "BODY") break;
        nodeNames.push(node.nodeName.toLowerCase());
        node = node.parentNode;
    }
    nodeNames.reverse();
    text += "\nDepth: " + nodeNames.length;
    text += ",  Children: " + childCount;
    text += "\nPath: " + nodeNames.join("/");
    ui.meta.value = text;      // update the textbox
}

function focusTextBox(/*TextBox*/ tbox) {
    tbox.focus();
    tbox.select();
}

function execQuery() {
    ui.queryCount.value = "";
    var query = $.trim(ui.query.value);
    if (query == "") {
        clearQuery();
        return;
    }
    
    if (ui.queryToggle.label == "CSS")
        execCssQuery(query);
    else
        execXPathQuery(query);
}

function clearQuery() {
    clearQuerySelectBoxes(ui.browser.contentDocument);
    ui.queryCount.value = "";
}

function execCssQuery(/*string*/ query) {
    var nodes = $(query, ui.browser.contentDocument.body).get();
    createQuerySelectBoxes(ui.browser.contentDocument, nodes);
    
    ui.queryCount.value = nodes.length.toString() + " nodes";
}

function execXPathQuery(/*string*/ query) {
    var doc = ui.browser.contentDocument;
    
    var nodes = [];
    var nodeIter = doc.evaluate(query, doc, null, XPathResult.ANY_TYPE, null);
    //jsdump(nodeIter.resultType);
    
    node = nodeIter.iterateNext();
    while (node) {
        nodes.push(node);
        node = nodeIter.iterateNext();
    }
    ui.queryCount.value = nodes.length.toString() + " nodes";
    
    if (!nodes.length)
        return;
        
    switch (nodes[0].nodeType) {
        case Node.ELEMENT_NODE:
            createQuerySelectBoxes(doc, nodes);
            break;
        case Node.TEXT_NODE:
            var texts = [nodes[i].textContent for (i in nodes)];
            window.openDialog("textResults.xul", 
                "dlg", "centerscreen=yes,resizable=yes,status=yes", texts);
            break;
    }
}

$(window).bind("load", onLoad);